<?php
declare(strict_types=1);
/**
 * This file is part of Hyperf.
 *
 * @link     https://www.hyperf.io
 * @document https://hyperf.wiki
 * @contact  group@hyperf.io
 * @license  https://github.com/hyperf/hyperf/blob/master/LICENSE
 */

namespace App\Controller;

use Hyperf\Di\Annotation\Inject;
use Hyperf\HttpServer\Annotation\Controller;
use Hyperf\HttpServer\Annotation\GetMapping;
use Hyperf\HttpServer\Annotation\PostMapping;
use Hyperf\HttpServer\Annotation\RequestMapping;

use App\Service\SomeService;

use Hyperf\DbConnection\Db;
use Hyperf\Coroutine\Coroutine;
use Hyperf\Coroutine\WaitGroup;
use Hyperf\Coroutine\Parallel;
use Swoole\Coroutine\Channel;

use Hyperf\Event\EventDispatcher;
use App\Event\OrderCreated;

#[Controller(prefix: '/employeeex')]
class EmployeeexController extends AbstractController
{
    #[GetMapping(path: '')]
    public function index()
    {
        try {
            // $config = [
            //     'host' => env('DB_HOST', 'mysql'),
            //     'port' => (int)env('DB_PORT', 3306),
            //     'dbname' => env('DB_DATABASE', 'mydatabase'),
            //     'username' => env('DB_USERNAME', 'root'),
            //     'password' => env('DB_PASSWORD', '123456'),
            //     'charset' => env('DB_CHARSET', 'utf8mb4'),
            // ];
            // $pdo = new PDO(
            //     'mysql:host=mysql;port=3306;dbname=mydatabase', // 显式指定端口
            //     'root', 
            //     '123456',
            //     [
            //         PDO::ATTR_EMULATE_PREPARES => false,
            //         PDO::ATTR_STRINGIFY_FETCHES => false,
            //     ]
            // );
            //  // 如果连接成功，执行一个简单的查询来验证连接
            //  $list = $pdo->query("SELECT id, des, des1, des3, tabnm, isdel, updated_at, created_at FROM testtab_2020 LIMIT 100");
            //  $results = $list->fetchAll();

            $count = Db::select(' SELECT count(id) as allcount FROM testtab_2020 ')[0];
            $results = Db::select('SELECT id,des,des1,des3,tabnm,isdel,updated_at,created_at FROM testtab_2020 WHERE 1 LIMIT  100');
            // 查询所有 
            return [
                'code' => 1,
                'count' => $count,
                'message' => "查询成功",
                'data' => $results,

            ];
        } catch (\PDOException $e) {
            return ['status' => 'error', 'message' => $e->getMessage()];
        }
    }

    #[GetMapping(path: 'get')]
    public function get()
    {
        // 查询
        $data = $this->request->all();
        $count = Db::select(' SELECT count(id) as allcount FROM testtab_2020  ')[0];
        $results = Db::select('SELECT id,des,des1,des3,tabnm,isdel,updated_at,created_at FROM testtab_2020 WHERE 1 LIMIT  100');
        return [
            'code' => 1,
            'count' => $count->allcount,
            'message' => "查询成功",
            'data' => $results,

        ];
    }


    #[GetMapping(path: 'getnormal')]
    public function getnormal()
    {
        // 传统查询
        $data = $this->request->all();
        //等待第一个查询
        $count = Db::select(' SELECT count(id) as allcount FROM testtab_2020  ')[0];
        //第一个查询有结果后开始第二个查询
        $results = Db::select('SELECT id,des,des1,des3,tabnm,isdel,updated_at,created_at FROM testtab_2020 WHERE 1 LIMIT  100');
        //查询最长的查询时间取两个查询之和
        return [
            'code' => 1,
            'count' => $count->allcount,
            'message' => "查询成功",
            'data' => $results,
        ];
    }

    // 方式1 - 使用Coroutine::create创建协程
    #[GetMapping(path: 'getmethod1')]
    public function getmethod1()
    {
        // 使用 &$result 传递引用在协程中是不安全的
        // 应该使用协程上下文或Channel
        $result = [
            'code' => 1,
            'count' => 0,
            'message' => "查询成功",
            'data' => []
        ];

        $wg = new WaitGroup();
        $wg->add(2);
        //异步查询1
        Coroutine::create(function () use (&$result, $wg) {
            $count = Db::select(' SELECT count(id) as allcount FROM testtab_2020  ')[0];
            $result['count'] = $count->allcount;
            $wg->done();
        });
        //异步查询2
        Coroutine::create(function () use (&$result, $wg) {
            $list = Db::select('SELECT id,des,des1,des3,tabnm,isdel,updated_at,created_at FROM testtab_2020 WHERE 1 LIMIT  100');
            $result['data'] = $list;
            $wg->done();
        });
        //等待两个协程执行完成，最大值取查询最长的那个
        $wg->wait();
        return $result;
    }

    // 方式1 - 扩展 协程与通道 (Channel) 
    //#[GetMapping(path: 'getmethod1ex')]
    // public function getmethod1ex()
    // {
    //     $channel = new Channel(2);

    //     Coroutine::create(function () use ($channel) {
    //         $count = Db::select('SELECT count(id) as allcount FROM testtab_2020')[0];
    //         $channel->push(['count' => $count->allcount]);
    //     });

    //     Coroutine::create(function () use ($channel) {
    //         $list = Db::select('SELECT id,des,... FROM testtab_2020 LIMIT 100');
    //         $channel->push(['data' => $list]);
    //     });

    //     $result = [
    //         'code' => 1,
    //         'message' => "查询成功",
    //         'count' => 0,
    //         'data' => []
    //     ];

    //     for ($i = 0; $i < 2; $i++) {
    //         $partial = $channel->pop();
    //         $result = array_merge($result, $partial);
    //     }

    //     return $result;
    // }

    // 方式2 - 使用Parallel简化并发操作
    #[GetMapping(path: 'getmethod2')]
    public function getmethod2()
    {
        $parallel = new Parallel();

        $parallel->add(function () {
            return Db::select(' SELECT count(id) as allcount FROM testtab_2020  ')[0];
        });

        $parallel->add(function () {
            return Db::select('SELECT id,des,des1,des3,tabnm,isdel,updated_at,created_at FROM testtab_2020 WHERE 1 LIMIT  100');
        });

        $results = $parallel->wait();

        return [
            'code' => 1,
            'count' => $results[0]->allcount,
            'message' => "查询成功",
            'data' => $results[1]
        ];
    }

    // // 方式3 - 使用协程查询多个用户
    // public function multiUser(array $ids)
    // {
    //     $parallel = new Parallel();

    //     foreach ($ids as $id) {
    //         $parallel->add(function () use ($id) {
    //             return Db::query('SELECT * FROM `users` WHERE `id` = ?', [$id]);
    //         });
    //     }

    //     $results = $parallel->wait();

    //     return $results;
    // }

    // 支持多种HTTP方法
    #[RequestMapping(path: 'save', methods: ['get', 'POST'])]
    public function save()
    {
        // 保存
        $data = $this->request->all();
        if (empty($data)) {
            return ['code' => 0, 'message' => "数据为空", 'param' => $data];
        }
        $des = '';
        if (empty($data['id'])) {
            $des = '新增';
            $ids = Db::select(' SELECT max(id) as id FROM testtab_2020  ')[0];
            Db::table('testtab_2020')->insert([
                ['id' => $ids->id++, 'des' => $data['des'], 'des1' => $data['des1'], 'des3' => $data['des3'], 'created_at' => date('Y-m-d H:i:s')]
            ]);
        } else {
            $des = '修改';
            Db::table('testtab_2020')->where('id', $data['id'])
                ->update(['des' => $data['des'], 'des1' => $data['des1'], 'des3' => $data['des3'], 'updated_at' => date('Y-m-d H:i:s')]);
        }
        return ['code' => 1, 'message' => $des . "成功", 'param' => $data];
    }

    #[GetMapping(path: 'delete')]
    public function delete()
    {
        //删除
        $data = $this->request->all();
        if (empty($data['id'])) {
            return ['code' => 0, 'message' => "需要删除的记录为空"];
        }
        Db::table('testtab_2020')->where('id', '=', $data['id'])->delete();
        return ['code' => 1, 'message' => "删除成功", 'data' => $data];
    }

    #[GetMapping(path: 'test')]
    public function test(SomeService $service)
    {
        $result1 = $service->someMethod('Hyperf');
        $result2 = $service->anotherMethod(4, 2);
        
        echo '开始';
        $dispatcher = $this->container->get(EventDispatcher::class);
        $dispatcher->dispatch(new OrderCreated('这是事件机制喔'));
        echo '结束';
        return [
            'result1' => $result1,
            'result2' => $result2,
        ];
    }

}